package jers.impl;

import java.rmi.RemoteException;

import jers.Callback;
import jers.Factory;
import jers.JERS;
import jers.Job;
import jers.Manager;
import jers.Provider;
import jers.Result;
import jers.Service;
import jers.util.Configurator;
import jers.util.Daemon;
import jers.util.FileServer;
import jers.util.Logger;
import jers.util.SimpleConfigurator;
import jers.util.SimpleLogger;
import jers.util.ThreadPool;
import jers.util.Utility;
import jers.util.daemon.RMIDDaemon;
import jers.util.file.SimpleHttpFileServer;
import jers.util.pool.SimpleThreadPool;


/**
 * Classe reponsavel por criar as instancias dos objetos do sistema.<br>
 * Ela constroi instancias das classes contidos no pacote {@code jers.impl}.
 * 
 * @see {@link RemoteManager}, {@link RemoteService}. {@link RemoteResult},
 * 		{@link RemoteJob}, {@link RemoteProvider}, 
 * 		{@link SimpleHttpFileServer}, {@link SimpleThreadPool}, 
 * 		{@link SimpleLogger}, {@link SimpleConfigurator}.
 * 
 * @author 
 * 		<a href="mailto:felipe.zappala@gmail.com">
 * 			Luis Felipe Zappala
 * 		</a> [ <a href="http://lncc.br/ist">ISTCC-P</a> / 2009 ]
 */
public final class SystemFactory implements Factory {
	
	public Callback newCallback(Callback callback) {
		try {
			// Verifica se a instancia callback e valida e se ja esta decorada
			if (callback != null 
					&& !callback.getClass().getName().startsWith("$Proxy")) {
				return RemoteProxyCallback.getInstance(callback);
			}
			return callback;
			
		} catch (Exception e) {
			throw new RuntimeException(Utility.concat(
					"Error initializing the instance: ", 
					RemoteProxyCallback.class.getName()), e);
		}
	}

	public Callback newCallback(Runnable callback) {
		return new WaiterCallback(new RemoteCallback(callback));
	}
	
	public Configurator newConfigurator() {
		return new SimpleConfigurator();
	}

	public FileServer newFileServer() {
		return new SimpleHttpFileServer();
	}

	public Job newJob(Runnable job) {
		return new RemoteJob(job);
	}

	public Logger newLogger() {
		return new SimpleLogger();
	}

	public Manager newManager() {
		return new RemoteManager();
	}

	public Provider newProvider() {
		return RemoteProvider.getInstance();
	}

	public Result newResult() {
		return new RemoteResult();
	}

	public Service newService() {
		try {
			boolean useActivation = Boolean.valueOf(JERS.config
					.getProperty("jers.service.activation.use"));
			
			if (useActivation) {
				return RemoteActivableService.getInstance();
			}
			return new RemoteService();
			
		} catch (RemoteException e) {
			throw new RuntimeException(Utility.concat(
					"Error initializing the instance: ", 
					RemoteService.class.getName()), e);
		}
		
	}

	public ThreadPool newThreadPool() {
		return new SimpleThreadPool();
	}
	
	public Daemon newRMIDDaemon() {
		return new RMIDDaemon();
	}

	/**
	 * A clonagem nao e suportada por esse objeto.
	 */
	@Override
	protected Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException("Operation not supported");
	}
	
}
